use macroquad::prelude::draw_text_ex;
use macroquad::prelude::screen_height;
use macroquad::prelude::Font;
use macroquad::prelude::TextParams;

use crate::utils::in_range;

pub const FONT_SIZE: u16 = 16;
const SPACE_BETWEEN_ROWS: f32 = 16.0;

pub struct Label {
    raw_string: String,
    fitted_strings: Option<Vec<String>>,
}

impl Label {
    pub fn new(string: &str) -> Self {
        return Self {
            raw_string: string.to_owned(),
            fitted_strings: None,
        };
    }
    pub fn fit(self, width_chars: u32) -> Self {
        return Self {
            fitted_strings: Some(
                textwrap::wrap(&self.raw_string, width_chars as usize)
                    .into_iter()
                    .map(|s| s.to_string())
                    .collect(),
            ),
            ..self
        };
    }
    pub fn line_count(&self) -> usize {
        match &self.fitted_strings {
            Some(v) => v.len(),
            None => 1,
        }
    }
    pub fn height(&self) -> f32 {
        return SPACE_BETWEEN_ROWS * self.line_count() as f32;
    }
    pub fn strings(&self) -> Vec<&str> {
        match &self.fitted_strings {
            Some(strings) => strings.into_iter().map(|s| s.as_str()).collect(),
            None => vec![&self.raw_string],
        }
    }
    pub fn draw(&self, x: f32, y: f32, font: Font) {
        for (i, string) in self.strings().into_iter().enumerate() {
            let slice = string.to_string();
            let i_as_f32 = i as f32;
            let text_y = y + i_as_f32 * SPACE_BETWEEN_ROWS;
            if in_range(text_y, 0.0, screen_height())
                || in_range(text_y + FONT_SIZE as f32, 0.0, screen_height())
            {
                draw_text_ex(
                    &slice,
                    x,
                    text_y,
                    TextParams {
                        font,
                        font_size: FONT_SIZE,
                        ..Default::default()
                    },
                );
            }
        }
    }
}
